home *** CD-ROM | disk | FTP | other *** search
/ Speccy ClassiX 1998 / Speccy ClassiX 98.iso / amiga_system / the_aminet / dev / gcc / ixemulsrc.lha / ixemul-41.4 / library / stat.c < prev    next >
C/C++ Source or Header  |  1995-09-27  |  7KB  |  241 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  stat.c,v 1.1.1.1 1994/04/04 04:30:35 amiga Exp
  20.  *
  21.  *  stat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:35  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  22:03:10  mwild
  26.  *  grp/oth support, plus new feature
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include "ixemul.h"
  35. #include "kprintf.h"
  36.  
  37. #if __GNUC__ != 2
  38. #define alloca __builtin_alloca
  39. #endif
  40.  
  41. #ifndef ST_ROOT
  42. #define ST_ROOT        1
  43. #define ST_USERDIR     2
  44. #define ST_SOFTLINK    3
  45. #define ST_LINKDIR    4
  46. #define ST_FILE        -3
  47. #define ST_LINKFILE    -4
  48. #endif
  49.  
  50. #ifndef ERROR_IS_SOFT_LINK
  51. #define ERROR_IS_SOFT_LINK  233
  52. #endif
  53.  
  54. /* currently, links are quite buggy.. hope this get cleaned up RSN ;-) */
  55.  
  56. extern BPTR __lock (), __llock ();
  57.  
  58. static int
  59. __stat(char *fname, struct stat *stb, BPTR (*lock_func)())
  60. {
  61.   BPTR lock;
  62.   long mode;
  63.   struct FileInfoBlock *fib;
  64.   struct InfoData *info;
  65.   int omask;
  66.   int error;
  67.  
  68.   bzero (stb, sizeof(*stb));
  69.  
  70.   omask = syscall (SYS_sigsetmask, ~0);
  71.  
  72.   if (!(lock = (*lock_func) (fname, ACCESS_READ)))
  73.     {
  74.       int err = IoErr ();
  75.  
  76.       /* take special care of NIL:, /dev/null and friends ;-) */
  77.       if (err == 4242)
  78.         {
  79.           stb->st_mode = S_IFCHR | 0777;
  80.           stb->st_nlink = 1;
  81.           stb->st_blksize = ix.ix_fs_buf_factor * 512;
  82.           stb->st_blocks = 0;
  83.           goto rest_sigmask;
  84.         }
  85.  
  86.       KPRINTF (("__stat: lock %s failed, err = %ld.\n", fname, err));
  87.       if (err == ERROR_IS_SOFT_LINK)
  88.     {
  89.       /* provide some default stb.. we can't get anymore info than
  90.        * that. Symlinks should work with Lock(), but till now they
  91.        * don't ;-( */
  92.       stb->st_handler = (int) DeviceProc ((UBYTE *)fname);
  93.       stb->st_dev = (dev_t) stb->st_handler;
  94.       /* HELP! no way to reach the fib of this entry except when
  95.        * scanning the parent directory, but this is NOT acceptable ! */
  96.       stb->st_ino = 123;
  97.       /* this is the most important entry ;-) */
  98.       stb->st_mode = S_IFLNK | 0777;
  99.       stb->st_size = 1024; /* again, this should be availabe... */
  100.       stb->st_nlink = 1;
  101.       stb->st_uid = stb->st_gid = stb->st_rdev = 0;
  102.       /* again, these values ARE accessible, but only by ExNext */
  103.       stb->st_atime = stb->st_mtime = stb->st_ctime = 0;
  104.       stb->st_blksize = stb->st_blocks = 0;
  105.       goto rest_sigmask;
  106.         }
  107. error:
  108.       syscall (SYS_sigsetmask, omask);
  109.       errno = __ioerr_to_errno (err);
  110.       KPRINTF (("ioerr = %ld, &errno = %lx, errno = %ld\n", err, &errno, errno));
  111.       return -1;
  112.     }
  113.   KPRINTF (("__stat: lock %s ok.\n",fname));
  114.  
  115.   /* alloca() returns stack memory, so it's guaranteed to be word 
  116.    * aligned (anything else would be deadly for the sp...) Since DOS needs
  117.    * long aligned data, we'll allocate 1 word more and adjust as needed */
  118.   fib = alloca (sizeof(*fib) + 2);
  119.   /* DON'T use LONG_ALIGN(alloca(..)), the argument is evaluated more than once! */
  120.   fib = LONG_ALIGN (fib);
  121.  
  122.   info = alloca (sizeof(*info) + 2);
  123.   info = LONG_ALIGN (info);
  124.  
  125.   if (!(Examine (lock, fib)))
  126.     {
  127.       __unlock (lock);
  128.       goto error;
  129.     }
  130.  
  131.   stb->st_nlink = 1; /* always one link entry per file, unless... */
  132.  
  133.   mode = 0L;
  134.   stb->st_amode = fib->fib_Protection;
  135.   if (!(fib->fib_Protection & FIBF_EXECUTE))
  136.     mode |= S_IXUSR;
  137.   else if (fib->fib_Protection & FIBF_SCRIPT)
  138.     mode |= S_IXUSR;
  139.   if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
  140.     mode |= S_IWUSR;
  141.   if (!(fib->fib_Protection & FIBF_READ))
  142.     mode |= S_IRUSR;
  143. #ifdef FIBF_GRP_EXECUTE
  144.   /* FIBF_GRP_EXECUTE requires at least OS3 headers */
  145.   if (fib->fib_Protection & FIBF_GRP_EXECUTE)
  146.     mode |= S_IXGRP;
  147.   if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
  148.     mode |= S_IWGRP;
  149.   if (fib->fib_Protection & FIBF_GRP_READ)
  150.     mode |= S_IRGRP;
  151.   if (fib->fib_Protection & FIBF_OTR_EXECUTE)
  152.     mode |= S_IXOTH;
  153.   if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
  154.     mode |= S_IWOTH;
  155.   if (fib->fib_Protection & FIBF_OTR_READ)
  156.     mode |= S_IROTH;
  157. #endif
  158.  
  159.   switch (fib->fib_DirEntryType)
  160.     {
  161.     case ST_LINKDIR:
  162.       stb->st_nlink ++;  /* we never get more than a link count of two.. */
  163.     case ST_ROOT:
  164.     case ST_USERDIR:
  165.       mode |= S_IFDIR;
  166.       break;
  167.  
  168.     /* at the moment, we NEVER get this entry, since we can't get a lock
  169.      * on a symlink */
  170.     case ST_SOFTLINK:
  171.       mode |= S_IFLNK;
  172.       break;
  173.  
  174.     case ST_LINKFILE:
  175.       stb->st_nlink ++;
  176.     case ST_FILE:
  177.     default:
  178.       mode |= S_IFREG;
  179.     }
  180.  
  181.   stb->st_mode = mode;
  182.   
  183.   /* support for annotated attributes (cool name ;-)) */
  184.   if (! strncmp (fib->fib_Comment, "!SP!", 4))
  185.     {
  186.       int sp_mode, sp_addr;
  187.  
  188.       if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
  189.         stb->st_mode = sp_mode;
  190.     }
  191.   
  192.   /* some kind of a default-size for directories... */
  193.   stb->st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  194.   stb->st_handler = (long)((struct FileLock *)((long)lock << 2))->fl_Task;
  195.   stb->st_dev = (dev_t)stb->st_handler; /* trunc to 16 bit */
  196.   stb->st_ino = fib->fib_DiskKey; 
  197.   stb->st_atime =
  198.   stb->st_ctime =
  199.   stb->st_mtime = (8*365+2)*24*3600 + ix.ix_gmt_offset +
  200.           fib->fib_Date.ds_Days * 24 * 60 * 60 +
  201.           fib->fib_Date.ds_Minute * 60 +
  202.           fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  203.   /* in a try to count the blocks used for filemanagement, we add one for
  204.    * the fileheader. Note, that this is wrong for large files, where there
  205.    * are some extension-blocks as well */
  206.   stb->st_blocks = fib->fib_NumBlocks + 1;
  207.   
  208.   bzero (info, sizeof (*info));
  209.   stb->st_blksize = 0;
  210.   if (Info(lock, info))
  211.     /* optimal for fileio is as high as possible ;-) This is a
  212.      * compromise between "as high as possible" and not too restricitve
  213.      * for people low on memory */
  214.     stb->st_blksize = info->id_BytesPerBlock * ix.ix_fs_buf_factor;
  215.  
  216.   if (! stb->st_blksize) stb->st_blksize = 512;
  217.  
  218.   __unlock (lock);
  219.  
  220. rest_sigmask:
  221.   syscall (SYS_sigsetmask, omask);
  222.   errno = 0;
  223.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  224.   return 0;
  225. }
  226.  
  227. /***************************************************************************/
  228.  
  229. int
  230. stat (char *fname, struct stat *stb)
  231. {
  232.   return __stat (fname, stb, __lock);
  233. }
  234.  
  235. int
  236. lstat (char *fname, struct stat *stb)
  237. {
  238.   return __stat (fname, stb, __llock);
  239. }
  240.  
  241.